<?php

namespace App\Models;

use App\Http\Common\Globals;
use App\Http\Common\MyUtils;
use App\Models\Myquery\Builder;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Session;

/**
 * 旧的基类 当列表 详情 修改删除等 都是 基础的简单的 没有多个关联的，用此基类会极大方便
 * Class BaseHard
 * @package App\Models
 */
class BaseOld extends Model
{
    private $myColumns = [];// 存储需要查询的列
    // 如果没有created_at 与 updated_at就是false,否则是true
    public $timestamps = true;
    // 批量赋值 $fillable[白名单] 与 $guarded[黑名单]
    protected $guarded = [];
    protected static $tableName = '';
    public $redisTable = [];// redis需要更新的一些表,应该去掉表的前缀
    public $redisClass = [];// redis需要更新的一些表,的类
    protected $perPage = 20;// 每页的数量
    public $usedColumn = [];// 已经被使用了 的列名 查询
    public $uniqColumn = '';// 唯一列名 查询
    public $finalArr = [];// 请求的数组参数
    public $finalArr_ = [];// 请求的数组参数
    public $findAllList = "";// 查询所有列表的sql语句
    public $findAllList_ = "";// $findAllList的原来的模样
    public $mainTableAlias = "";// 要查询的根据的表的别名
    public $column = "*";// 数据库需要查询的列
    public $filterColumn = [];// 数据库查询需要过滤掉的列
    public $countColumn = "count(*)";// 查询的列
    public $request = null;// request请求
    public $projectIdOpen = true;// 打开project_id
    public $filter = false;// 打开违法字段过滤的功能
    public function __construct(array $attributes = [])
    {
        if (!$this->findAllList)
            $this->findAllList = env("DB_PREFIX").$this->table;
        $this->findAllList = $this->wramp($this->findAllList);
        $this->findAllList_ = $this->findAllList;
        $this->finalArr = $this->finalArr_;
        $this->request = Globals::$request;
        $this->implodedColumn();
        parent::__construct($attributes);
    }

    /**
     * 将sql包围
     * @param $sql
     * @return string
     */
    public function wramp($sql){
        $pos = strpos($sql," ");
        if ($pos===false){
            return "select #c# from " .$sql." sa where #p#";
        }else{
            return "select #c# from ( " .$sql." ) sa where #p#";
        }
    }
    /**
     * 将列转换为字符串,顺便将不需要的列过滤掉
     */
    public function implodedColumn(){
        if (is_array($this->column)){
            if ($this->filterColumn){
                array_filter($this->column,function ($k){
                    if(in_array($this->column[$k],$this->filterColumn)){//过滤掉数组
                        unset($this->column[$k]);
                    }
                },ARRAY_FILTER_USE_KEY);
            }
            $this->column = implode(',',$this->column);
        }
    }
    /**
     * 条件查询的条件的新增
     * @param $request
     */
    public function myQuery($request)
    {
        $this->myColumns = [];
        if ($this->mainTableAlias){
            Globals::$orderBy = $this->mainTableAlias.".id desc";
        }else{
            Globals::$orderBy = "id desc";
        }
        Globals::$alias = $this->mainTableAlias;
        $this->rebackSql();// sql还原，防止发生sql语句自动拼接的冲突
        $this->finalArr  = $this->finalArr_;// sql还原，防止发生sql语句自动拼接的冲突
        $this->request = $request;
        $this->replacePrev($request);
    }

    /**
     * 之前需要替换的
     * @param $request
     */
    public function replacePrev($request){
    }
    /**
     * 强sql语句还原到以前的状态
     */
    public function rebackSql(){// sql还原，防止发生sql语句自动拼接的冲突
        $this->findAllList = $this->findAllList_;
    }
    /**
     * 拿到是否是住户
     */
    public function getIfIsHouswhold(){
        $userId = Session::get('user_id');
        $one = Houswholds::where('user_id',$userId)->get("*")->first();
        if (!$one){// 如果用户不是住户的话，就不能投诉建议
            Globals::$error = "你不是住户，不能进行该操作，只有成为了相应的住户才能进行操作。";
            return false;
        }else{
            return true;
        }
    }

    /**
     * 一般要先query,然后再运行 list 然后再是运行 count
     * 得到所有的 用户列表
     * @param $limit 每页多少
     * @param $page 第几页
     * @return true
     */
    public function list($limit,$page){
        $this->myQuery(Globals::$request);
        return $this->list_($limit,$page);
    }
    /**
     * 一般要先query,然后再运行 list 然后再是运行 count
     * 得到所有的 用户列表
     * @param $limit 每页多少
     * @param $page 第几页
     * @return true
     */
    public function list_($limit,$page){
        $this->implodedColumn();
        // 将变量#column#替换成 列 $column
        $temp = str_replace(["#column#","#c#"],[$this->column,$this->column],$this->findAllList);
        if ($limit!=-1 && $page!=-1){
            $temp = $this->pageLimit($limit,$page,$temp);
        }
        $this->ifDeteted();
        return $this->filterColumn(MyUtils::dbSelect($temp,$this->finalArr,true));
    }

    /**
     * 判断是否删除
     */
    public function ifDeteted(){
    }
    /**
     * 一般要先query,然后再运行 list 然后再是运行 count
     * 得到所有的 用户列表
     * @param null $request
     * @return true
     */
    public function one(){
        $this->myQuery(Globals::$request);
        return $this->one_();
    }
    /**
     * 一般要先query,然后再运行 list 然后再是运行 count
     * 得到所有的 用户列表
     * @return true
     */
    public function one_(){
        $this->implodedColumn();
        // 将变量#column#替换成 列 $column
        $temp = str_replace(["#column#","#c#"],[$this->column,$this->column],$this->findAllList);
        $temp = $this->pageLimit(1,1,$temp);
        $this->ifDeteted();
        return $this->filterColumn(MyUtils::dbSelect($temp,$this->finalArr));
    }

    /**
     * 得到所有的  数目
     * @param null $request
     * @return mixed
     */
    public function count(){
        $this->myQuery(Globals::$request);
        return $this->count_();
    }
    /**
     * 得到所有的  数目
     * @return mixed
     */
    public function count_(){
        // 将  #column# 替换成 count(*) as countAll
        $temp = str_replace(["#column#","#c#"],[$this->countColumn." as countAll",$this->countColumn." as countAll"],$this->findAllList);
        $this->ifDeteted();
        // 查询数量
        $res =  MyUtils::dbSelect($temp,$this->finalArr);
        if (is_array($res)){
            return $res[0]->caountAll;
        }else{
            return $res->countAll;
        }
    }

    /**
     * 得到其他的 方法 求和
     * @param $column
     * @param null $request
     * @return mixed
     */
    public function others($column,$request=null){
        if ($request)Globals::$request = $request;
        $this->myQuery(Globals::$request);
        return $this->others_($column);
    }
    /**
     * 得到其他的 方法 求和
     * @param $column
     * @return mixed
     */
    public function others_($column){
        $temp = str_replace(["#column#","#c#"],[$column." as countAll",$column." as countAll"],$this->findAllList);
        $this->ifDeteted();
        // 查询数量
        $res =  MyUtils::dbSelect($temp,$this->finalArr);
        if (is_array($res)){
            return $res[0]->countAll;
        }else{
            return $res->countAll;
        }
    }
    /**
     * 查询分页
     * @param $limit
     * @param $page
     * @param $temp
     * @return mixed
     */
    public function  pageLimit($limit,$page,$temp){
        if ($temp){
            // 分页
            $temp .= " limit ".$limit;
            $temp .= " offset ".($limit * ($page - 1));
        }else{
            // 分页
            $this->findAllList .= " limit ".$limit;
            $this->findAllList .= " offset ".($limit * ($page - 1));
        }
        return $temp;
    }
    /**
     * 保存
     * @param $request
     * @return int
     */
    public function  store($request){
        return self::insertGetId(MyUtils::getDbKnowArray($request));
    }
    /**
     * 更新
     * @param $request
     * @return int
     */
    public function  storeUpdate($request){
        return self::find(MyUtils::sg($request,"id"))->update(MyUtils::getDbKnowArray($request));
    }
    /**
     * 详情
     * request 为 FormRequest
     * @param $request
     * @return bool|true
     */
    public function  storeDetail($request){
        $this->implodedColumn();
        $this->replacePrev($request);
        // $this->myQuery($request);
        // 将变量#column#替换成 列 $column
        $temp = str_replace(["#column#","#c#"],[$this->column,$this->column],$this->findAllList);
        $this->ifDeteted();
        if ($request->id) {
            if (env('ID_ENCODE_OPEN')){
                $request->id = MyUtils::decodeColumn($request->id);
            }
            $temp = $temp.' and id = "'.$request->id.'"';
            $res = MyUtils::dbSelect($temp,$this->finalArr);
            if ($res){
                return $this->filterColumn($res);
            }else{
                Globals::$error = "查询不到该条数据";
                return false;
            }
        }else{
            Globals::$error = "请传递需要查询的id";
            return false;
        }
    }

    /**
     * 过滤掉不需要返给前端的列
     * @param $data 需要过滤的数据
     * @return 需要过滤的数据
     */
    public function filterColumn($data){
        // 表示是返回的数组
        if (!$this->filterColumn){
            return $data;
        }
        if (is_array($data) && isset($data[0])){
            foreach ($data as $k=>$v){
                foreach ($this->filterColumn as $vv){
                    unset($data[$k]->$vv);
                }
            }
        }
        if (is_object($data)){
            foreach ($this->filterColumn as $v){
                unset($data->$v);
            }
        }
        return $data;
    }
    /**
     * 删除数据
     * @param $request
     * @return bool
     * @throws Exception
     */
    public function  storeDelete($request){
        $ids = MyUtils::sg($request,"ids");
        // 批量删除
        $res  = true;
        foreach ($ids as $k=>$v){
            // 删除
            if (!$one = self::find($v)){
                $res = false && $res;
                Globals::$error .= "第".($k+1)."条要删除的数据不存在；";
                break;
            }
            $res0 = $one->delete();
            $res = $res0 && $res;
            if (!$res0){
                Globals::$error .= "第".($k+1)."条删除失败；";
                break;
            }
        }
        return $res;
    }
    /**
     * 得到唯一的code 订单的编号 32 位
     * @param $class
     * @param string $name
     * @return string
     */
    public function getUniqueCode($class,$name='code'){
        // 得到唯一的openId
        $code = date('Ymdhms').MyUtils::randMath(6);
        $codeCount = $class::where($name,$code)->get()->count();
        // 不为空 再生成一遍
        if ($codeCount) $code = $this->getUniqueCode($class);
        return $code;
    }

    /**
     * @param $request request 请求
     * @param $column 列明
     * @param $condition 条件 like in =
     * @param string $value 是需要传递的值
     * @param string $orAnd 是 or 还是 and 的查询
     */
    public function sqlSearch($request,$column,$condition,$value='',$orAnd = 'and'){
        $c = MyUtils::sg($request,$column);
        if (is_array($c)){
            $c = implode(',',$c);
        }
        $c = trim($c);
        if ($value!==''){
            if (is_array($value)){
                $value = implode(',',$value);
            }
            $c = trim($value);
        }
        if ($c!=='') {
            $this->generateUniqueColumn($column);
            switch ($condition){
                case "like":
                    $this->findAllList .= " $orAnd $column $condition :$this->uniqColumn";
                    $this->finalArr[$this->uniqColumn] = "%".$c."%";
                    break;
                case "in":
                    if ($c){
                        $this->findAllList .= " $orAnd $column $condition ($c)";
                    }
                    break;
                case "sameTimeLike":// $column必须为数组，$value 不能为空
                    $this->findAllList .= "  $orAnd (";
                    $this->findAllList .= "$column[0] like :$this->uniqColumn ";
                    $this->finalArr[$this->uniqColumn] = "%".$c."%";
                    $this->findAllList .= " or ";
                    $this->generateUniqueColumn($column[0]);
                    $this->findAllList .= "$column[1] like :$this->uniqColumn ";
                    $this->finalArr[$this->uniqColumn] = "%".$c."%";
                    $this->findAllList .= ") ";
                case "is":
                    $this->findAllList .= " $orAnd $column $condition $c";
                    break;
                default:
                    $this->findAllList .= " $orAnd $column $condition :$this->uniqColumn";
                    $this->finalArr[$this->uniqColumn] = $c;
                    break;
            }
        }
    }

    /**
     * 生成唯一未被使用过的列名
     * @param $column
     */
    public function generateUniqueColumn(&$column){
        $this->removeColumnAlias($column);
        $column_ = $column;
        $this->addColumnAlias($column);
        if (is_array($column_) && count($column_)){
            $column_ = $column_[0];
        }
        $this->uniqColumn = $column_.count($this->usedColumn);
        $this->usedColumn[] = $this->uniqColumn;
        $this->myColumns[] = $column_;
    }

    /**
     * 给列新增别名
     * @param $column
     */
    public function addColumnAlias(&$column){
        if ($this->mainTableAlias){// 要根据的查询的表的别名
            $column = $this->mainTableAlias.'.'.$column;
        }
    }

    /**
     * 给列移除别名
     * @param $column
     */
    public function removeColumnAlias(&$column){
        if ($this->mainTableAlias){
            $column = str_replace($this->mainTableAlias.'.','',$column);
        }
    }

    /**
     * 通过查询的条件生成相应的sql语句 是可以得到两种 字段 同时查询的
     * @param array $column 列
     * @param $condition 条件
     * @param $value 列的值
     * @param string $orAnd and or
     */
    public function sqlSearch2(array $column,$condition,$value,$orAnd = 'and'){
        if ($value){
            if (!is_array($value)){
                $temp = $value;
                $value = [];
                foreach ($column as $k=>$v){
                    $value[$k] = $temp;
                }
            }
            $this->generateUniqueColumn($column);
            switch ($condition){
                case "like":// $column必须为数组，$value 不能为空
                    $this->findAllList .= "  $orAnd (";
                    foreach ($column as $k=>$v){
                        $this->generateUniqueColumn($v);
                        $this->findAllList .= "$v $condition :$this->uniqColumn ";
                        $this->finalArr[$this->uniqColumn] = "%".$value[$k]."%";
                        if ($k !== count($column)-1){
                            $this->findAllList .= " or ";
                        }
                    }
                    $this->findAllList .= ") ";
                    break;
                case "is":
                case "=":// $column必须为数组，$value 不能为空
                    $this->findAllList .= "  $orAnd (";
                    foreach ($column as $k=>$v){
                        $this->generateUniqueColumn($v);
                        $this->findAllList .= "$v $condition :$this->uniqColumn ";
                        $this->finalArr[$this->uniqColumn] = $value[$k];
                        if ($k !== count($column)-1){
                            $this->findAllList .= " or ";
                        }
                    }
                    $this->findAllList .= ") ";
                    break;
                default:// $column必须为数组，$value 不能为空
                    $this->findAllList .= "  $orAnd (";
                    foreach ($column as $k=>$v){
                        $this->generateUniqueColumn($v);
                        $this->findAllList .= "$v $condition[$k] :$this->uniqColumn ";
                        $this->finalArr[$this->uniqColumn] = $value[$k];
                        if ($k !== count($column)-1){
                            $this->findAllList .= " or ";
                        }
                    }
                    $this->findAllList .= ") ";
                    break;
            }
        }
    }

    /**
     * 时间区间 sql查询
     * @param $request 请求
     * @param string $value 值的 列名称
     * @param string $column 列
     * @param string $orAnd
     */
    public function sqlTimeRange($request,$value='',$column='created_at',$orAnd = 'and'){
        if (in_array($column,$this->myColumns)){// 防止发生重复查询
            return;
        }
        if ($request->$value
            && $request->$value[0] && $request->$value[1]
            && $request->$value[0]!='undefined'&& $request->$value[1]!='undefined') {
            $this->generateUniqueColumn($column);
            $this->findAllList .= " $orAnd $column between :$this->uniqColumn";
            $this->finalArr[$this->uniqColumn] = $request->$value[0]." 00:00:00:00";
            $this->generateUniqueColumn($column);
            $this->findAllList .= " and :$this->uniqColumn ";
            $this->finalArr[$this->uniqColumn] = $request->$value[1]." 23:59:59:59";
        }
    }
    /**
     * 给sql新增 字符
     * @param $param
     */
    public function sqlAdd($param){
        $this->findAllList .= ' '.$param.' ';
    }
    /**
     * 拿到时间区间
     * @param $request
     * @param $value
     * @return mixed
     */
    public function getTimeRange($value){
        $finalArr[] = $value[0]." 00:00:00:00";
        $finalArr[] = $value[1]." 23:59:59:59";
        return $finalArr;
    }
    /**
     * 给以下的方法统一加上相应的 project_id ，就是说会自动加上这些，然后查询，新增的时候都会自动加上
     * @param $column
     * @param null $operator
     * @param null $value
     * @param string $boolean
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public static function where($column, $operator = null, $value = null, $boolean = 'and')
    {
        $instance = new static;
        if ($instance->projectIdOpen){
            return $instance->newQuery()->where($column, $operator, $value, $boolean)
                // 实现能够统一的每个wehere都能自动加上这个
                ->where('project_id',MyUtils::getSessionConfig("PROJECT_ID"));
        }else{
            return $instance->newQuery()->where($column, $operator, $value, $boolean);
        }
    }
    public static function insert(array $values)
    {
        $instance = new static;
        if ($instance->projectIdOpen){
            $values['project_id'] = MyUtils::getSessionConfig("PROJECT_ID");
        }
        return $instance->newQuery()->insert($values);
    }
    public static function insertGetId(array $values,$sequence = null)
    {
        $instance = new static;
        if ($instance->projectIdOpen){
            $values['project_id'] = MyUtils::getSessionConfig("PROJECT_ID");
        }
        return $instance->newQuery()->insertGetId($values, $sequence);
    }
    public static function select($column)
    {
        $instance = new static;
        if ($instance->projectIdOpen){
            return $instance->newQuery()->select($column)
                // 实现能够统一的每个wehere都能自动加上这个
                ->where('project_id',MyUtils::getSessionConfig("PROJECT_ID"));
        }else{
            return $instance->newQuery()->select($column);
        }
    }
    /**
     * 为模型创建一个新的有说服力的查询生成器。
     * @param $query
     * @return Builder
     */
    public function newEloquentBuilder($query)
    {
        // 返回的是我自己的builder
        return new Builder($query);
    }
}
